//
// Created by konglinglong on 2020/9/6.
//

#include "../include/l2Api.h"
#include "fs/fs.h"

S_RanL2Context *gpRanL2Context = NULL;

int32_t RAN_L2_LoadCellConfig(S_RanL2CellInst *pCellInst, S_RanCellContext *pCellContext)
{
    pCellInst->inUse = pCellContext->inUse;

    pCellInst->slotNum = gNormalCpScs2SlotNumTable[pCellContext->dlSubcarrierSpacing];

    pCellInst->pL2L1CpMsgQue = pCellContext->pL2L1CpMsgQue;
    pCellInst->pL1L2CpMsgQue = pCellContext->pL1L2CpMsgQue;
    pCellInst->pL2L1UpMsgQue = pCellContext->pL2L1UpMsgQue;
    pCellInst->pL1L2UpMsgQue = pCellContext->pL1L2UpMsgQue;

    return O5G_RC_OK;
}

int32_t RAN_L2_LoadNodeBConfig(S_RanL2NbInst *pNbInst, S_RanNodeBContext *pNbContext)
{
    int32_t rc;
    uint32_t loop;

    pNbInst->nbId = pNbContext->nbId;
    pNbInst->inUse = pNbContext->inUse;

    pNbInst->cellNum = pNbContext->cellNum;
    for (loop = 0; loop < pNbInst->cellNum; loop++)
    {
        rc = RAN_L2_LoadCellConfig(&pNbInst->cellInst[loop], &pNbContext->cellContext[loop]);
        IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_LoadNodeBConfig() RAN_L2_LoadCellConfig() error!\n");
    }

    return O5G_RC_OK;
}

int32_t RAN_L2_LoadConfig()
{
    int32_t rc;
    uint32_t loop;

    gpRanL2Context->nbNum = gpRanContext->nbNum;
    for (loop = 0; loop < gpRanL2Context->nbNum; loop++)
    {
        rc = RAN_L2_LoadNodeBConfig(&gpRanL2Context->nbInst[loop], &gpRanContext->nbContext[loop]);
        IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_LoadConfig() RAN_L2_LoadNodeBConfig() error!\n");
    }

    return O5G_RC_OK;
}

int32_t RAN_L2_Init(void)
{
    int32_t rc;
    uint32_t nbLoop;
    uint32_t cellLoop;
    S_RanL2NbInst *pNbInst;
    S_RanL2CellInst *pCellInst;
    char ttiIntPipeName[256];

    gpRanL2Context = OS_MemCalloc(1, sizeof(S_RanL2Context));
    IF_RETURN(==, NULL, gpRanL2Context, O5G_RC_ER, "RAN_L2_Init() OS_MemCalloc() error!\n");

    rc = RAN_L2_LoadConfig();
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() RAN_L2_LoadConfig() error!\n");

    RAN_INIT_INST_IDX(gpRanL2Context);

    gpRanL2Context->pL3iL1iMsgQue = VarRB_Create(NULL, 2 * 1024 * 1024, VAR_RB_TYPE_MPSC);
    gpRanL2Context->pL1iL3iMsgQue = VarRB_Create(NULL, 2 * 1024 * 1024, VAR_RB_TYPE_MPSC);

    IF_RETURN(==, NULL, gRanL2FsIntf[gpRanContext->funcSplitOpt].Init, O5G_RC_ER, "RAN_L2_Init() Init == NULL!\n");
    rc = gRanL2FsIntf[gpRanContext->funcSplitOpt].Init();
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() Init() error!\n");

    for (nbLoop = 0; nbLoop < RAN_NODEB_NUM_MAX; nbLoop++)
    {
        pNbInst = &gpRanL2Context->nbInst[nbLoop];
        IF_CONTINUE(==, FALSE, pNbInst->inUse, NO_LOG_MESSAGE);
        for (cellLoop = 0; cellLoop < RAN_CELL_NUM_MAX; cellLoop++)
        {
            pCellInst = &pNbInst->cellInst[cellLoop];
            IF_CONTINUE(==, FALSE, pCellInst->inUse, NO_LOG_MESSAGE);

            rc = OS_SelectInit(&pCellInst->ulHiTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(ulHiTtiSelector) error!\n");
            rc = OS_SelectInit(&pCellInst->dlHiTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(dlHiTtiSelector) error!\n");
            rc = OS_SelectInit(&pCellInst->ulLoTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(ulLoTtiSelector) error!\n");
            rc = OS_SelectInit(&pCellInst->dlLoTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(dlLoTtiSelector) error!\n");
            rc = OS_SelectInit(&pCellInst->mschSchTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(mschSchTtiSelector) error!\n");
            rc = OS_SelectInit(&pCellInst->mschAlgTtiSelector, NULL);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(mschAlgTtiSelector) error!\n");

            pCellInst->ulHiPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->ulHiPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(ulHiPoller) error!\n");
            pCellInst->dlHiPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->dlHiPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(dlHiPoller) error!\n");
            pCellInst->ulLoPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->ulLoPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(ulLoPoller) error!\n");
            pCellInst->dlLoPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->dlLoPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(dlLoPoller) error!\n");
            pCellInst->mschSchPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->mschSchPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(mschSchPoller) error!\n");
            pCellInst->mschAlgPoller = POLLER_Create(POLL_FD_NUM_MAX);
            IF_RETURN(==, NULL, pCellInst->mschAlgPoller, O5G_RC_ER, "RAN_L2_Init() POLLER_Create(mschAlgPoller) error!\n");

            snprintf(ttiIntPipeName, sizeof(ttiIntPipeName), "%s_nb%u_cell%u", RAN_TTI_INT_PIPE_NAME, nbLoop, cellLoop);
            rc = OS_SelectInit(&pCellInst->ttiIntSelector, ttiIntPipeName);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Init() OS_SelectInit(ttiIntSelector) error!\n");
            CSP_LOG_INF(RAN_MD_L1_COMM, "RAN_L2_Init() nb[%u] cell[%u] TTI_INT_PIPE[%s].\n", nbLoop, cellLoop, (char *)ttiIntPipeName);
        }
    }

    CSP_LOG_INF(RAN_MD_L2_COMM, "RAN_L2_Init() success.\n");

    return O5G_RC_OK;
}

int32_t RAN_L2_Final(void)
{
    int32_t rc;
    uint32_t nbLoop;
    uint32_t cellLoop;
    S_RanL2NbInst *pNbInst;
    S_RanL2CellInst *pCellInst;

    IF_RETURN(==, NULL, gRanL2FsIntf[gpRanContext->funcSplitOpt].Final, O5G_RC_ER, "RAN_L2_Final() Final == NULL!\n");
    rc = gRanL2FsIntf[gpRanContext->funcSplitOpt].Final();
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() Final() error!\n");

    for (nbLoop = 0; nbLoop < RAN_NODEB_NUM_MAX; nbLoop++)
    {
        pNbInst = &gpRanL2Context->nbInst[nbLoop];
        IF_CONTINUE(==, FALSE, pNbInst->inUse, NO_LOG_MESSAGE);
        for (cellLoop = 0; cellLoop < RAN_CELL_NUM_MAX; cellLoop++)
        {
            pCellInst = &pNbInst->cellInst[cellLoop];
            IF_CONTINUE(==, FALSE, pCellInst->inUse, NO_LOG_MESSAGE);

            rc = OS_SelectFinal(&pCellInst->ulHiTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(ulHiTtiSelector) error!\n");
            rc = OS_SelectFinal(&pCellInst->dlHiTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(dlHiTtiSelector) error!\n");
            rc = OS_SelectFinal(&pCellInst->ulLoTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(ulLoTtiSelector) error!\n");
            rc = OS_SelectFinal(&pCellInst->dlLoTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(dlLoTtiSelector) error!\n");
            rc = OS_SelectFinal(&pCellInst->mschSchTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(mschSchTtiSelector) error!\n");
            rc = OS_SelectFinal(&pCellInst->mschAlgTtiSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(mschAlgTtiSelector) error!\n");

            POLLER_Destroy(pCellInst->ulHiPoller);
            POLLER_Destroy(pCellInst->dlHiPoller);
            POLLER_Destroy(pCellInst->ulLoPoller);
            POLLER_Destroy(pCellInst->dlLoPoller);
            POLLER_Destroy(pCellInst->mschSchPoller);
            POLLER_Destroy(pCellInst->mschAlgPoller);

            rc = OS_SelectFinal(&pCellInst->ttiIntSelector);
            IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Final() OS_SelectFinal(ttiIntSelector) error!\n");
        }
    }

    VarRB_Destroy(gpRanL2Context->pL3iL1iMsgQue);
    VarRB_Destroy(gpRanL2Context->pL1iL3iMsgQue);

    OS_MemFree(gpRanL2Context);

    CSP_LOG_INF(RAN_MD_L2_COMM, "RAN_L2_Final() success.\n");

    return O5G_RC_OK;
}

int32_t RAN_L2_Start(void)
{
    int32_t rc;

    IF_RETURN(==, NULL, gRanL2FsIntf[gpRanContext->funcSplitOpt].Start, O5G_RC_ER,
        "RAN_L2_Start() Start == NULL!\n");
    rc = gRanL2FsIntf[gpRanContext->funcSplitOpt].Start();
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Start() Start() error!\n");

    CSP_LOG_INF(RAN_MD_L2_COMM, "RAN_L2_Start() success.\n");

    return O5G_RC_OK;
}

int32_t RAN_L2_Stop(void)
{
    int32_t rc;

    IF_RETURN(==, NULL, gRanL2FsIntf[gpRanContext->funcSplitOpt].Stop, O5G_RC_ER,
        "RAN_L2_Stop() Stop == NULL!\n");
    rc = gRanL2FsIntf[gpRanContext->funcSplitOpt].Stop();
    IF_RETURN(!=, O5G_RC_OK, rc, O5G_RC_ER, "RAN_L2_Stop() Stop() error!\n");

    CSP_LOG_INF(RAN_MD_L2_COMM, "RAN_L2_Stop() success.\n");

    return O5G_RC_OK;
}

